#!python
# Copyright (C) 2016-2020 Intel Corporation
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted for any purpose (including commercial purposes)
# provided that the following conditions are met:
#
# 1. Redistributions of source code must retain the above copyright notice,
#    this list of conditions, and the following disclaimer.
#
# 2. Redistributions in binary form must reproduce the above copyright notice,
#    this list of conditions, and the following disclaimer in the
#    documentation and/or materials provided with the distribution.
#
# 3. In addition, redistributions of modified forms of the source or binary
#    code must carry prominent notices stating that the original code was
#    changed and the date of the change.
#
#  4. All publications or advertising materials mentioning features or use of
#     this software are asked, but not required, to acknowledge that it was
#     developed by Intel Corporation and credit the contributors.
#
# 5. Neither the name of Intel Corporation, nor the name of any Contributor
#    may be used to endorse or promote products derived from this software
#    without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
# DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
# (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
# ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
"""Build cart src"""

import os

# pylint: disable=no-name-in-module
# pylint: disable=import-error
import SCons.Action
# pylint: enable=import-error
# pylint: enable=no-name-in-module

SRC = ['crt_bulk.c', 'crt_context.c', 'crt_corpc.c',
       'crt_ctl.c', 'crt_debug.c', 'crt_group.c', 'crt_hg.c', 'crt_hg_proc.c',
       'crt_init.c', 'crt_iv.c', 'crt_register.c',
       'crt_rpc.c', 'crt_self_test_client.c', 'crt_self_test_service.c',
       'crt_swim.c', 'crt_tree.c', 'crt_tree_flat.c', 'crt_tree_kary.c',
       'crt_tree_knomial.c', 'crt_hlc.c']

# pylint: disable=unused-argument
def macro_expand(target, source, env):
    """Function for PostAction"""
    scope = r"'/struct [^ ]*_\(in\|out\) {/,/};/p'"
    sed_e = r"-e 's/\s\s*/ /g' -e 's/};struct /};\nstruct /g'"
    sed_d = r"-e 's/\([{;]\) /\1\t/g' -e 's/\([{;]\)/\1\n/g'"
    grepv = r"'struct sockaddr_in {'"
    tgts = ""
    for tgt in target:
        tgts += "%s_grep " % tgt.abspath
        os.system("sed -n %s %s | tr -d '\\n' | sed %s > %s_grep"
                  % (scope, tgt.abspath, sed_e, tgt.abspath))
    h_name = "src/cart/_structures_from_macros_.h"
    h_file = os.path.join(Dir('#').abspath, h_name)
    with open(h_file, "w") as outfile:
        outfile.write("/* Automatically generated with structures\n"
                      " * expanded from CRT_RPC_DECLARE() macros\n *\n")
        with open("LICENSE", "r") as infile:
            for line in infile.readlines():
                if line == "\n":
                    outfile.write(" *\n")
                else:
                    outfile.write(" * " + line)
            infile.close()
        outfile.write(" */\n\n")
        outfile.close()
    if tgts != "":
        os.system("cat %s | grep -v %s | sort -u | sed %s >> %s"
                  % (tgts, grepv, sed_d, h_file))
# pylint: enable=unused-argument

def scons():
    """Scons function"""

    Import('env', 'prereqs', 'swim_targets', 'gurt_lib', 'CART_VERSION')

    env.AppendUnique(LIBPATH=[Dir('.')])

    denv = env.Clone()

    denv.AppendUnique(CPPPATH=['#/src/cart'])
    denv.AppendUnique(LIBS=['gurt'])
    prereqs.require(denv, 'mercury')
    denv.AppendUnique(RPATH=['$PREFIX/lib'])

    cart_targets = denv.SharedObject(SRC)

    compiler = env.get('COMPILER').lower()
    if compiler != 'covc':
        pp_env = Environment(TOOLS=['default', 'extra'])
        pp_env.AppendUnique(CPPPATH=['src/include', 'src/cart'])
        prereqs.require(pp_env, 'mercury', headers_only=True)

        # pylint: disable=no-member
        pp_files = pp_env.Preprocess(SRC)
        pp_env.AddPostAction(pp_files, SCons.Action.Action(macro_expand, None))
        # pylint: enable=no-member

        denv.Requires(cart_targets, pp_files)

    cart_lib = denv.SharedLibrary('libcart', [cart_targets, swim_targets],
                                  SHLIBVERSION=CART_VERSION)
    denv.Requires(cart_lib, [swim_targets, gurt_lib])
    denv.InstallVersionedLib('$PREFIX/lib/', cart_lib,
                             SHLIBVERSION=CART_VERSION)

    Default(cart_lib)
    Export('cart_lib', 'cart_targets')

if __name__ == "SCons.Script":
    scons()
